@@ -5,10 +5,14 @@ from django.contrib import admin |
||
| 5 | 5 |
from django.contrib.auth.hashers import make_password |
| 6 | 6 |
from pysnippets.strsnippets import strip |
| 7 | 7 |
|
| 8 |
-from account.models import AdministratorInfo |
|
| 8 |
+from account.models import AdministratorInfo, UserInfo |
|
| 9 | 9 |
from equipment.models import IsolationPointInfo |
| 10 | 10 |
|
| 11 | 11 |
|
| 12 |
+class UserInfoAdmin(admin.ModelAdmin): |
|
| 13 |
+ list_display = ('user_id', 'unionid', 'openid', 'openid_miniapp', 'name', 'sex', 'nickname', 'avatar', 'phone', 'country', 'province', 'city', 'user_status', 'updated_at', 'created_at')
|
|
| 14 |
+ |
|
| 15 |
+ |
|
| 12 | 16 |
class AdministratorInfoAdmin(admin.ModelAdmin): |
| 13 | 17 |
list_display = ('admin_id', 'phone', 'password', 'encryption', 'name', 'point_id', 'point_name', 'user_status', 'status', 'created_at', 'updated_at')
|
| 14 | 18 |
list_filter = ('user_status', 'status', 'point_name')
|
@@ -30,4 +34,5 @@ class AdministratorInfoAdmin(admin.ModelAdmin): |
||
| 30 | 34 |
obj.save() |
| 31 | 35 |
|
| 32 | 36 |
|
| 37 |
+admin.site.register(UserInfo, UserInfoAdmin) |
|
| 33 | 38 |
admin.site.register(AdministratorInfo, AdministratorInfoAdmin) |
@@ -0,0 +1,40 @@ |
||
| 1 |
+# Generated by Django 3.2.6 on 2021-08-12 05:49 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+import shortuuidfield.fields |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+class Migration(migrations.Migration): |
|
| 8 |
+ |
|
| 9 |
+ dependencies = [ |
|
| 10 |
+ ('account', '0001_initial'),
|
|
| 11 |
+ ] |
|
| 12 |
+ |
|
| 13 |
+ operations = [ |
|
| 14 |
+ migrations.CreateModel( |
|
| 15 |
+ name='UserInfo', |
|
| 16 |
+ fields=[ |
|
| 17 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 18 |
+ ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
|
|
| 19 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 20 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 21 |
+ ('user_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='用户唯一标识', max_length=22, null=True, unique=True)),
|
|
| 22 |
+ ('unionid', models.CharField(blank=True, db_index=True, help_text='微信 Unionid', max_length=32, null=True, unique=True, verbose_name='unionid')),
|
|
| 23 |
+ ('openid', models.CharField(blank=True, db_index=True, help_text='微信公众号 Openid', max_length=32, null=True, unique=True, verbose_name='openid')),
|
|
| 24 |
+ ('openid_miniapp', models.CharField(blank=True, db_index=True, help_text='微信小程序 Openid', max_length=32, null=True, unique=True, verbose_name='openid_miniapp')),
|
|
| 25 |
+ ('name', models.CharField(blank=True, help_text='用户姓名', max_length=255, null=True, verbose_name='name')),
|
|
| 26 |
+ ('sex', models.IntegerField(choices=[(0, '未知'), (1, '男'), (2, '女')], default=0, help_text='用户性别', verbose_name='sex')),
|
|
| 27 |
+ ('nickname', models.CharField(blank=True, help_text='用户昵称', max_length=255, null=True, verbose_name='nickname')),
|
|
| 28 |
+ ('avatar', models.CharField(blank=True, help_text='用户头像', max_length=255, null=True, verbose_name='avatar')),
|
|
| 29 |
+ ('phone', models.CharField(blank=True, db_index=True, help_text='用户电话', max_length=11, null=True, verbose_name='phone')),
|
|
| 30 |
+ ('country', models.CharField(blank=True, help_text='用户国家', max_length=255, null=True, verbose_name='country')),
|
|
| 31 |
+ ('province', models.CharField(blank=True, help_text='用户省份', max_length=255, null=True, verbose_name='province')),
|
|
| 32 |
+ ('city', models.CharField(blank=True, help_text='用户城市', max_length=255, null=True, verbose_name='city')),
|
|
| 33 |
+ ('user_status', models.IntegerField(choices=[(0, '未验证'), (1, '已激活'), (2, '已禁用'), (3, '已删除'), (10, '已分配')], default=0, help_text='用户状态', verbose_name='user_status')),
|
|
| 34 |
+ ], |
|
| 35 |
+ options={
|
|
| 36 |
+ 'verbose_name': '用户信息', |
|
| 37 |
+ 'verbose_name_plural': '用户信息', |
|
| 38 |
+ }, |
|
| 39 |
+ ), |
|
| 40 |
+ ] |
@@ -2,10 +2,70 @@ |
||
| 2 | 2 |
|
| 3 | 3 |
from django.db import models |
| 4 | 4 |
from django.utils.translation import ugettext_lazy as _ |
| 5 |
-from django_models_ext import BaseModelMixin |
|
| 5 |
+from django_models_ext import BaseModelMixin, SexModelMixin |
|
| 6 | 6 |
from shortuuidfield import ShortUUIDField |
| 7 | 7 |
|
| 8 | 8 |
|
| 9 |
+class UserInfo(BaseModelMixin): |
|
| 10 |
+ UNVERIFIED = 0 |
|
| 11 |
+ ACTIVATED = 1 |
|
| 12 |
+ DISABLED = 2 |
|
| 13 |
+ DELETED = 3 |
|
| 14 |
+ ASSIGN = 10 |
|
| 15 |
+ |
|
| 16 |
+ USER_STATUS = ( |
|
| 17 |
+ (UNVERIFIED, '未验证'), |
|
| 18 |
+ (ACTIVATED, '已激活'), |
|
| 19 |
+ (DISABLED, '已禁用'), |
|
| 20 |
+ (DELETED, '已删除'), |
|
| 21 |
+ (ASSIGN, '已分配'), |
|
| 22 |
+ ) |
|
| 23 |
+ |
|
| 24 |
+ user_id = ShortUUIDField(_('user_id'), max_length=32, blank=True, null=True, help_text='用户唯一标识', db_index=True, unique=True)
|
|
| 25 |
+ |
|
| 26 |
+ # 微信授权用户 |
|
| 27 |
+ unionid = models.CharField(_('unionid'), max_length=32, blank=True, null=True, help_text='微信 Unionid', db_index=True, unique=True)
|
|
| 28 |
+ openid = models.CharField(_('openid'), max_length=32, blank=True, null=True, help_text='微信公众号 Openid', db_index=True, unique=True)
|
|
| 29 |
+ openid_miniapp = models.CharField(_('openid_miniapp'), max_length=32, blank=True, null=True, help_text='微信小程序 Openid', db_index=True, unique=True)
|
|
| 30 |
+ |
|
| 31 |
+ # 用户基本信息 |
|
| 32 |
+ name = models.CharField(_('name'), max_length=255, blank=True, null=True, help_text='用户姓名')
|
|
| 33 |
+ sex = models.IntegerField(_('sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text='用户性别')
|
|
| 34 |
+ nickname = models.CharField(_('nickname'), max_length=255, blank=True, null=True, help_text='用户昵称')
|
|
| 35 |
+ avatar = models.CharField(_('avatar'), max_length=255, blank=True, null=True, help_text='用户头像')
|
|
| 36 |
+ phone = models.CharField(_('phone'), max_length=11, blank=True, null=True, help_text='用户电话', db_index=True)
|
|
| 37 |
+ country = models.CharField(_('country'), max_length=255, blank=True, null=True, help_text='用户国家')
|
|
| 38 |
+ province = models.CharField(_('province'), max_length=255, blank=True, null=True, help_text='用户省份')
|
|
| 39 |
+ city = models.CharField(_('city'), max_length=255, blank=True, null=True, help_text='用户城市')
|
|
| 40 |
+ |
|
| 41 |
+ user_status = models.IntegerField(_('user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text='用户状态')
|
|
| 42 |
+ |
|
| 43 |
+ class Meta: |
|
| 44 |
+ verbose_name = _('用户信息')
|
|
| 45 |
+ verbose_name_plural = _('用户信息')
|
|
| 46 |
+ |
|
| 47 |
+ def __unicode__(self): |
|
| 48 |
+ return '%d' % self.pk |
|
| 49 |
+ |
|
| 50 |
+ @property |
|
| 51 |
+ def data(self): |
|
| 52 |
+ return {
|
|
| 53 |
+ 'user_id': self.user_id, |
|
| 54 |
+ 'unionid': self.unionid, |
|
| 55 |
+ 'openid': self.openid, |
|
| 56 |
+ 'openid_miniapp': self.openid_miniapp, |
|
| 57 |
+ 'name': self.name, |
|
| 58 |
+ 'sex': self.sex, |
|
| 59 |
+ 'nickname': self.nickname, |
|
| 60 |
+ 'avatar': self.avatar, |
|
| 61 |
+ 'phone': self.phone, |
|
| 62 |
+ 'country': self.country, |
|
| 63 |
+ 'province': self.province, |
|
| 64 |
+ 'city': self.city, |
|
| 65 |
+ 'user_status': self.user_status, |
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+ |
|
| 9 | 69 |
class AdministratorInfo(BaseModelMixin): |
| 10 | 70 |
ACTIVATED = 1 |
| 11 | 71 |
DISABLED = 2 |
@@ -12,8 +12,8 @@ from django_response import response |
||
| 12 | 12 |
from paginator import pagination |
| 13 | 13 |
from TimeConvert import TimeConvert as tc |
| 14 | 14 |
|
| 15 |
-from equipment.models import (IsolationPointInfo, ThermometerEquipmentInfo, ThermometerMeasureInfo, |
|
| 16 |
- ThermometerMeasureLogInfo) |
|
| 15 |
+from equipment.models import (IsolationPointInfo, IsolationPointUserInfo, ThermometerEquipmentInfo, |
|
| 16 |
+ ThermometerMeasureInfo, ThermometerMeasureLogInfo) |
|
| 17 | 17 |
from utils.age import stamp2age |
| 18 | 18 |
from utils.error.errno_utils import IsolationPointStatusCode, ThermometerEquipmentStatusCode |
| 19 | 19 |
|
@@ -135,6 +135,9 @@ def eqpt_result(request): |
||
| 135 | 135 |
).values('macid', 'temperature')
|
| 136 | 136 |
logs = {log.get('macid'): log.get('temperature') for log in logs}
|
| 137 | 137 |
|
| 138 |
+ infos = IsolationPointUserInfo.objects.filter(point_id=point_id, status=True).values('pk', 'fields')
|
|
| 139 |
+ infos = {info.get('pk'): info.get('fields') for info in infos}
|
|
| 140 |
+ |
|
| 138 | 141 |
total_active_eqpt_num = eqpts.count() |
| 139 | 142 |
has_upload_temperature_num = len(logs) |
| 140 | 143 |
temperature_over_375 = len([1 for temperature in logs.values() if temperature > 37.5]) |
@@ -142,7 +145,11 @@ def eqpt_result(request): |
||
| 142 | 145 |
if kw: |
| 143 | 146 |
eqpts = eqpts.filter(Q(name__icontains=kw) | Q(phone__icontains=kw)) |
| 144 | 147 |
eqpts, left = pagination(eqpts, page, num) |
| 145 |
- eqpts = [{**eqpt.data, **{'has_upload': eqpt.macid in logs, 'temperature': logs.get(eqpt.macid, 0)}} for eqpt in eqpts]
|
|
| 148 |
+ eqpts = [{**eqpt.data, **{
|
|
| 149 |
+ 'has_upload': eqpt.macid in logs, |
|
| 150 |
+ 'temperature': logs.get(eqpt.macid, 0), |
|
| 151 |
+ 'fields': infos.get(eqpt.ipui_pk, {}),
|
|
| 152 |
+ }} for eqpt in eqpts] |
|
| 146 | 153 |
|
| 147 | 154 |
return response(data={
|
| 148 | 155 |
'eqpts': eqpts, |
@@ -0,0 +1,168 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+import logging |
|
| 4 |
+ |
|
| 5 |
+from django.conf import settings |
|
| 6 |
+from django.db import transaction |
|
| 7 |
+from django_logit import logit |
|
| 8 |
+from django_response import response |
|
| 9 |
+from pywe_miniapp import get_session_info, get_session_key, get_userinfo, store_session_key |
|
| 10 |
+from pywe_storage import RedisStorage |
|
| 11 |
+ |
|
| 12 |
+from account.models import UserInfo |
|
| 13 |
+from utils.redis.connect import r |
|
| 14 |
+ |
|
| 15 |
+ |
|
| 16 |
+WECHAT = settings.WECHAT |
|
| 17 |
+logger = logging.getLogger('logit')
|
|
| 18 |
+ |
|
| 19 |
+ |
|
| 20 |
+@logit |
|
| 21 |
+@transaction.atomic |
|
| 22 |
+def get_userinfo_api(request): |
|
| 23 |
+ appId = request.POST.get('appId', 'MINIAPP')
|
|
| 24 |
+ |
|
| 25 |
+ wxcfg = WECHAT.get(appId, {})
|
|
| 26 |
+ |
|
| 27 |
+ appid = wxcfg.get('appID')
|
|
| 28 |
+ secret = wxcfg.get('appsecret')
|
|
| 29 |
+ |
|
| 30 |
+ code = request.POST.get('code', '')
|
|
| 31 |
+ encryptedData = request.POST.get('encryptedData', '')
|
|
| 32 |
+ iv = request.POST.get('iv', '')
|
|
| 33 |
+ |
|
| 34 |
+ # {u'avatarUrl': u'http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0',
|
|
| 35 |
+ # u'city': u'Guangzhou', |
|
| 36 |
+ # u'country': u'CN', |
|
| 37 |
+ # u'gender': 1, |
|
| 38 |
+ # u'language': u'zh_CN', |
|
| 39 |
+ # u'nickName': u'Band', |
|
| 40 |
+ # u'openId': u'oGZUI0egBJY1zhBYw2KhdUfwVJJE', |
|
| 41 |
+ # u'province': u'Guangdong', |
|
| 42 |
+ # u'unionId': u'ocMvos6NjeKLIBqg5Mr9QjxrP1FA', |
|
| 43 |
+ # u'watermark': {u'appid': u'wx4f4bc4dec97d474b', u'timestamp': 1477314187}}
|
|
| 44 |
+ session_key = get_session_key(appid=appid, secret=secret, code=code) |
|
| 45 |
+ # Get Userinfo |
|
| 46 |
+ userinfo = get_userinfo(appid=appid, secret=secret, code=code, session_key=session_key, encryptedData=encryptedData, iv=iv) |
|
| 47 |
+ |
|
| 48 |
+ # Get or Create User |
|
| 49 |
+ user, created = UserInfo.objects.select_for_update().get_or_create(unionid=userinfo.get('unionId', ''))
|
|
| 50 |
+ |
|
| 51 |
+ # Set User Key's Value |
|
| 52 |
+ user.unionid = userinfo.get('unionId', '')
|
|
| 53 |
+ user.openid_miniapp = userinfo.get('openId', '')
|
|
| 54 |
+ user.sex = userinfo.get('gender', '')
|
|
| 55 |
+ user.nickname = userinfo.get('nickName', '')
|
|
| 56 |
+ user.avatar = userinfo.get('avatarUrl', '')
|
|
| 57 |
+ user.country = userinfo.get('country', '')
|
|
| 58 |
+ user.province = userinfo.get('province', '')
|
|
| 59 |
+ user.city = userinfo.get('city', '')
|
|
| 60 |
+ user.user_status = UserInfo.ACTIVATED |
|
| 61 |
+ user.save() |
|
| 62 |
+ |
|
| 63 |
+ # Store SessionKey |
|
| 64 |
+ store_session_key(appid=appid, secret=secret, session_key=session_key, unid=user.user_id, storage=RedisStorage(r)) |
|
| 65 |
+ # Just for compatible because of store session_key has changed |
|
| 66 |
+ store_session_key(appid=appid, secret=secret, session_key=session_key, unid='', storage=RedisStorage(r)) |
|
| 67 |
+ |
|
| 68 |
+ return response(200, 'Mini App Login Success', '微信小程序登录成功', user.data) |
|
| 69 |
+ |
|
| 70 |
+ |
|
| 71 |
+@logit(res=True) |
|
| 72 |
+@transaction.atomic |
|
| 73 |
+def mini_login_api(request): |
|
| 74 |
+ appId = request.POST.get('appId', 'MINIAPP')
|
|
| 75 |
+ |
|
| 76 |
+ wxcfg = WECHAT.get(appId, {})
|
|
| 77 |
+ |
|
| 78 |
+ appid = wxcfg.get('appID')
|
|
| 79 |
+ secret = wxcfg.get('appsecret')
|
|
| 80 |
+ |
|
| 81 |
+ code = request.POST.get('code', '')
|
|
| 82 |
+ |
|
| 83 |
+ # // 正常返回的JSON数据包 |
|
| 84 |
+ # {
|
|
| 85 |
+ # "openid": "OPENID", |
|
| 86 |
+ # "session_key": "SESSIONKEY", |
|
| 87 |
+ # } |
|
| 88 |
+ # |
|
| 89 |
+ # // 满足UnionID返回条件时,返回的JSON数据包 |
|
| 90 |
+ # {
|
|
| 91 |
+ # "openid": "OPENID", |
|
| 92 |
+ # "session_key": "SESSIONKEY", |
|
| 93 |
+ # "unionid": "UNIONID" |
|
| 94 |
+ # } |
|
| 95 |
+ # // 错误时返回JSON数据包(示例为Code无效) |
|
| 96 |
+ # {
|
|
| 97 |
+ # "errcode": 40029, |
|
| 98 |
+ # "errmsg": "invalid code" |
|
| 99 |
+ # } |
|
| 100 |
+ session_info = get_session_info(appid=appid, secret=secret, code=code) |
|
| 101 |
+ logger.debug(session_info) |
|
| 102 |
+ session_key = session_info.get('session_key', '')
|
|
| 103 |
+ unionid = session_info.get('unionid', '')
|
|
| 104 |
+ openid = session_info.get('openid', '')
|
|
| 105 |
+ |
|
| 106 |
+ # Get or Create User |
|
| 107 |
+ user, created = UserInfo.objects.select_for_update().get_or_create(openid_miniapp=openid) |
|
| 108 |
+ |
|
| 109 |
+ # Set User Key's Value |
|
| 110 |
+ if unionid: |
|
| 111 |
+ user.unionid = unionid |
|
| 112 |
+ |
|
| 113 |
+ user.user_status = UserInfo.ACTIVATED |
|
| 114 |
+ user.save() |
|
| 115 |
+ |
|
| 116 |
+ # Store SessionKey |
|
| 117 |
+ store_session_key(appid=appid, secret=secret, session_key=session_key, unid=user.user_id, storage=RedisStorage(r)) |
|
| 118 |
+ # Just for compatible because of store session_key has changed |
|
| 119 |
+ store_session_key(appid=appid, secret=secret, session_key=session_key, unid='', storage=RedisStorage(r)) |
|
| 120 |
+ |
|
| 121 |
+ return response(200, 'Mini App Login Success', '微信小程序登录成功', user.data) |
|
| 122 |
+ |
|
| 123 |
+ |
|
| 124 |
+@logit |
|
| 125 |
+@transaction.atomic |
|
| 126 |
+def get_userinfo_api2(request): |
|
| 127 |
+ user_id = request.POST.get('user_id', '')
|
|
| 128 |
+ appId = request.POST.get('appId', 'MINIAPP')
|
|
| 129 |
+ |
|
| 130 |
+ wxcfg = WECHAT.get(appId, {})
|
|
| 131 |
+ |
|
| 132 |
+ appid = wxcfg.get('appID')
|
|
| 133 |
+ secret = wxcfg.get('appsecret')
|
|
| 134 |
+ |
|
| 135 |
+ encryptedData = request.POST.get('encryptedData', '')
|
|
| 136 |
+ iv = request.POST.get('iv', '')
|
|
| 137 |
+ |
|
| 138 |
+ try: |
|
| 139 |
+ user = UserInfo.objects.select_for_update().get(user_id=user_id, status=True) |
|
| 140 |
+ except UserInfo.DoesNotExist: |
|
| 141 |
+ return response() |
|
| 142 |
+ |
|
| 143 |
+ # {u'avatarUrl': u'http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0',
|
|
| 144 |
+ # u'city': u'Guangzhou', |
|
| 145 |
+ # u'country': u'CN', |
|
| 146 |
+ # u'gender': 1, |
|
| 147 |
+ # u'language': u'zh_CN', |
|
| 148 |
+ # u'nickName': u'Band', |
|
| 149 |
+ # u'openId': u'oGZUI0egBJY1zhBYw2KhdUfwVJJE', |
|
| 150 |
+ # u'province': u'Guangdong', |
|
| 151 |
+ # u'unionId': u'ocMvos6NjeKLIBqg5Mr9QjxrP1FA', |
|
| 152 |
+ # u'watermark': {u'appid': u'wx4f4bc4dec97d474b', u'timestamp': 1477314187}}
|
|
| 153 |
+ session_key = get_session_key(appid=appid, secret=secret, unid=user_id, storage=RedisStorage(r)) |
|
| 154 |
+ # Get Userinfo |
|
| 155 |
+ userinfo = get_userinfo(appid=appid, secret=secret, session_key=session_key, encryptedData=encryptedData, iv=iv) |
|
| 156 |
+ |
|
| 157 |
+ # Set User Key's Value |
|
| 158 |
+ user.unionid = userinfo.get('unionId', '')
|
|
| 159 |
+ user.openid_miniapp = userinfo.get('openId', '')
|
|
| 160 |
+ user.sex = userinfo.get('gender', '')
|
|
| 161 |
+ user.nickname = userinfo.get('nickName', '')
|
|
| 162 |
+ user.avatar = userinfo.get('avatarUrl', '')
|
|
| 163 |
+ user.country = userinfo.get('country', '')
|
|
| 164 |
+ user.province = userinfo.get('province', '')
|
|
| 165 |
+ user.city = userinfo.get('city', '')
|
|
| 166 |
+ user.save() |
|
| 167 |
+ |
|
| 168 |
+ return response(200, 'Mini App Get Userinfo Success', '微信小程序获取用户信息成功', user.data) |
@@ -6,7 +6,7 @@ from django_logit import logit |
||
| 6 | 6 |
from django_query import get_query_value |
| 7 | 7 |
from django_response import response |
| 8 | 8 |
|
| 9 |
-from equipment.models import IsolationPointInfo |
|
| 9 |
+from equipment.models import IsolationPointInfo, IsolationPointUserInfo, ThermometerEquipmentInfo |
|
| 10 | 10 |
from utils.error.errno_utils import IsolationPointStatusCode |
| 11 | 11 |
|
| 12 | 12 |
|
@@ -24,3 +24,46 @@ def measure_window(request): |
||
| 24 | 24 |
point.save() |
| 25 | 25 |
|
| 26 | 26 |
return response() |
| 27 |
+ |
|
| 28 |
+ |
|
| 29 |
+@logit |
|
| 30 |
+def get_point_fields(request): |
|
| 31 |
+ point_id = request.POST.get('point_id', '')
|
|
| 32 |
+ |
|
| 33 |
+ try: |
|
| 34 |
+ point = IsolationPointInfo.objects.get(point_id=point_id, status=True) |
|
| 35 |
+ except IsolationPointInfo.DoesNotExist: |
|
| 36 |
+ return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND) |
|
| 37 |
+ |
|
| 38 |
+ return response(data={
|
|
| 39 |
+ 'fields': point.point_fields, |
|
| 40 |
+ }) |
|
| 41 |
+ |
|
| 42 |
+ |
|
| 43 |
+@logit |
|
| 44 |
+def save_point_fields(request): |
|
| 45 |
+ point_id = request.POST.get('point_id', '')
|
|
| 46 |
+ user_id = request.POST.get('user_id', '')
|
|
| 47 |
+ fields = get_query_value(request, 'fields', val_cast_type='listjson') |
|
| 48 |
+ |
|
| 49 |
+ IsolationPointUserInfo.objects.create(point_id=point_id, user_id=user_id, fields=fields) |
|
| 50 |
+ |
|
| 51 |
+ return response() |
|
| 52 |
+ |
|
| 53 |
+ |
|
| 54 |
+@logit |
|
| 55 |
+def bind_eqpt(request): |
|
| 56 |
+ macid = request.POST.get('macid', '')
|
|
| 57 |
+ point_id = request.POST.get('point_id', '')
|
|
| 58 |
+ user_id = request.POST.get('user_id', '')
|
|
| 59 |
+ |
|
| 60 |
+ try: |
|
| 61 |
+ ipui = IsolationPointUserInfo.objects.get(point_id=point_id, user_id=user_id, status=True) |
|
| 62 |
+ except IsolationPointUserInfo.DoesNotExist: |
|
| 63 |
+ return response() |
|
| 64 |
+ |
|
| 65 |
+ ThermometerEquipmentInfo.objects.update_or_create(macid=macid, defaults={
|
|
| 66 |
+ 'ipui_pk': ipui.pk, |
|
| 67 |
+ }) |
|
| 68 |
+ |
|
| 69 |
+ return response() |
@@ -2,7 +2,7 @@ |
||
| 2 | 2 |
|
| 3 | 3 |
from django.conf.urls import url |
| 4 | 4 |
|
| 5 |
-from api import admin_views, eqpt_views, oauth_views, point_views |
|
| 5 |
+from api import admin_views, eqpt_views, mini_views, oauth_views, point_views |
|
| 6 | 6 |
|
| 7 | 7 |
|
| 8 | 8 |
urlpatterns = [ |
@@ -31,3 +31,16 @@ urlpatterns += [ |
||
| 31 | 31 |
urlpatterns += [ |
| 32 | 32 |
url(r'^upload/temperature$', eqpt_views.upload_temperature, name='upload_temperature'), |
| 33 | 33 |
] |
| 34 |
+ |
|
| 35 |
+# Mini App |
|
| 36 |
+urlpatterns += [ |
|
| 37 |
+ url(r'^mp/userinfo$', mini_views.get_userinfo_api, name='get_userinfo_api'), # 获取用户信息 |
|
| 38 |
+ url(r'^mp/login$', mini_views.mini_login_api, name='mini_login_api'), # 小程序登录 |
|
| 39 |
+ url(r'^mp/userinfo2$', mini_views.get_userinfo_api2, name='get_userinfo_api2'), # 获取用户信息 |
|
| 40 |
+] |
|
| 41 |
+ |
|
| 42 |
+urlpatterns += [ |
|
| 43 |
+ url(r'^mp/get_point_fields$', point_views.get_point_fields, name='get_point_fields'), |
|
| 44 |
+ url(r'^mp/save_point_fields$', point_views.save_point_fields, name='save_point_fields'), |
|
| 45 |
+ url(r'^mp/bind_eqpt$', point_views.bind_eqpt, name='bind_eqpt'), |
|
| 46 |
+] |
@@ -6,6 +6,7 @@ import time |
||
| 6 | 6 |
|
| 7 | 7 |
from django_six import CompatibilityBaseCommand |
| 8 | 8 |
from paho.mqtt import client as mqtt_client |
| 9 |
+ |
|
| 9 | 10 |
from api.eqpt_views import mqtt_upload_temperature |
| 10 | 11 |
|
| 11 | 12 |
|
@@ -3,16 +3,20 @@ |
||
| 3 | 3 |
from django.contrib import admin |
| 4 | 4 |
from django_admin import ReadOnlyModelAdmin |
| 5 | 5 |
|
| 6 |
-from equipment.models import (IsolationPointInfo, ThermometerEquipmentInfo, ThermometerMeasureInfo, |
|
| 7 |
- ThermometerMeasureLogInfo) |
|
| 6 |
+from equipment.models import (IsolationPointInfo, IsolationPointUserInfo, ThermometerEquipmentInfo, |
|
| 7 |
+ ThermometerMeasureInfo, ThermometerMeasureLogInfo) |
|
| 8 | 8 |
|
| 9 | 9 |
|
| 10 | 10 |
class IsolationPointInfoAdmin(admin.ModelAdmin): |
| 11 |
- list_display = ('point_id', 'point_name', 'point_measure_window', 'status', 'updated_at', 'created_at')
|
|
| 11 |
+ list_display = ('point_id', 'point_name', 'point_measure_window', 'point_fields', 'limit_scene_qrcode_url', 'status', 'updated_at', 'created_at')
|
|
| 12 |
+ |
|
| 13 |
+ |
|
| 14 |
+class IsolationPointUserInfoAdmin(admin.ModelAdmin): |
|
| 15 |
+ list_display = ('point_id', 'user_id', 'fields', 'status', 'updated_at', 'created_at')
|
|
| 12 | 16 |
|
| 13 | 17 |
|
| 14 | 18 |
class ThermometerEquipmentInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin): |
| 15 |
- list_display = ('eqpt_id', 'point_id', 'macid', 'sn', 'active_status', 'active_at', 'name', 'sex', 'birth_stamp', 'age', 'phone', 'remark', 'last_submit_at', 'eqpt_register_status', 'eqpt_register_result', 'status', 'updated_at', 'created_at')
|
|
| 19 |
+ list_display = ('eqpt_id', 'point_id', 'macid', 'sn', 'active_status', 'active_at', 'ipui_pk', 'name', 'sex', 'birth_stamp', 'age', 'phone', 'remark', 'last_submit_at', 'eqpt_register_status', 'eqpt_register_result', 'status', 'updated_at', 'created_at')
|
|
| 16 | 20 |
list_filter = ('point_id', 'status')
|
| 17 | 21 |
|
| 18 | 22 |
|
@@ -27,6 +31,7 @@ class ThermometerMeasureLogInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin): |
||
| 27 | 31 |
|
| 28 | 32 |
|
| 29 | 33 |
admin.site.register(IsolationPointInfo, IsolationPointInfoAdmin) |
| 34 |
+admin.site.register(IsolationPointUserInfo, IsolationPointUserInfoAdmin) |
|
| 30 | 35 |
admin.site.register(ThermometerEquipmentInfo, ThermometerEquipmentInfoAdmin) |
| 31 | 36 |
admin.site.register(ThermometerMeasureInfo, ThermometerMeasureInfoAdmin) |
| 32 | 37 |
admin.site.register(ThermometerMeasureLogInfo, ThermometerMeasureLogInfoAdmin) |
@@ -0,0 +1,46 @@ |
||
| 1 |
+# Generated by Django 3.2.6 on 2021-08-12 05:57 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+import jsonfield.fields |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+class Migration(migrations.Migration): |
|
| 8 |
+ |
|
| 9 |
+ dependencies = [ |
|
| 10 |
+ ('equipment', '0005_thermometermeasureloginfo_temperature_src'),
|
|
| 11 |
+ ] |
|
| 12 |
+ |
|
| 13 |
+ operations = [ |
|
| 14 |
+ migrations.AddField( |
|
| 15 |
+ model_name='isolationpointinfo', |
|
| 16 |
+ name='limit_scene_qrcode_url', |
|
| 17 |
+ field=models.CharField(blank=True, help_text='字段二维码', max_length=255, null=True, verbose_name='limit_scene_qrcode_url'), |
|
| 18 |
+ ), |
|
| 19 |
+ migrations.AddField( |
|
| 20 |
+ model_name='isolationpointinfo', |
|
| 21 |
+ name='point_fields', |
|
| 22 |
+ field=jsonfield.fields.JSONField(blank=True, default=[], help_text='字段列表', null=True, verbose_name='point_fields'), |
|
| 23 |
+ ), |
|
| 24 |
+ migrations.AddField( |
|
| 25 |
+ model_name='thermometerequipmentinfo', |
|
| 26 |
+ name='ipui_pk', |
|
| 27 |
+ field=models.IntegerField(default=0, help_text='隔离点用户录入PK', verbose_name='ipui_pk'), |
|
| 28 |
+ ), |
|
| 29 |
+ migrations.CreateModel( |
|
| 30 |
+ name='IsolationPointUserInfo', |
|
| 31 |
+ fields=[ |
|
| 32 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 33 |
+ ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
|
|
| 34 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 35 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 36 |
+ ('point_id', models.CharField(blank=True, db_index=True, help_text='隔离点唯一标识', max_length=32, null=True, verbose_name='point_id')),
|
|
| 37 |
+ ('user_id', models.CharField(blank=True, db_index=True, help_text='用户唯一标识', max_length=32, null=True, verbose_name='user_id')),
|
|
| 38 |
+ ('fields', jsonfield.fields.JSONField(blank=True, default=[], help_text='字段信息', null=True, verbose_name='fields')),
|
|
| 39 |
+ ], |
|
| 40 |
+ options={
|
|
| 41 |
+ 'verbose_name': '隔离点用户录入信息', |
|
| 42 |
+ 'verbose_name_plural': '隔离点用户录入信息', |
|
| 43 |
+ 'unique_together': {('point_id', 'user_id')},
|
|
| 44 |
+ }, |
|
| 45 |
+ ), |
|
| 46 |
+ ] |
@@ -11,9 +11,19 @@ from TimeConvert import TimeConvert as tc |
||
| 11 | 11 |
class IsolationPointInfo(BaseModelMixin): |
| 12 | 12 |
point_id = ShortUUIDField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True, unique=True)
|
| 13 | 13 |
point_name = models.CharField(_('point_name'), max_length=255, blank=True, null=True, help_text='隔离点名称')
|
| 14 |
+ |
|
| 14 | 15 |
# [{"start": "8:00", "end": "9:00"}, {"start": "12:00", "end": "14:00"}]
|
| 15 | 16 |
point_measure_window = JSONField(_('point_measure_window'), default=[], blank=True, null=True, help_text='隔离点测温时间段')
|
| 16 | 17 |
|
| 18 |
+ # {
|
|
| 19 |
+ # "type": "input", # input, select, file |
|
| 20 |
+ # "name": "", |
|
| 21 |
+ # "options": ["男", "女"], # type=select |
|
| 22 |
+ # } |
|
| 23 |
+ point_fields = JSONField(_('point_fields'), default=[], blank=True, null=True, help_text='字段列表')
|
|
| 24 |
+ |
|
| 25 |
+ limit_scene_qrcode_url = models.CharField(_('limit_scene_qrcode_url'), max_length=255, blank=True, null=True, help_text='字段二维码')
|
|
| 26 |
+ |
|
| 17 | 27 |
class Meta: |
| 18 | 28 |
verbose_name = _('隔离点信息')
|
| 19 | 29 |
verbose_name_plural = _('隔离点信息')
|
@@ -42,6 +52,33 @@ class IsolationPointInfo(BaseModelMixin): |
||
| 42 | 52 |
return '' |
| 43 | 53 |
|
| 44 | 54 |
|
| 55 |
+class IsolationPointUserInfo(BaseModelMixin): |
|
| 56 |
+ point_id = models.CharField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True)
|
|
| 57 |
+ |
|
| 58 |
+ user_id = models.CharField(_('user_id'), max_length=32, blank=True, null=True, help_text='用户唯一标识', db_index=True)
|
|
| 59 |
+ |
|
| 60 |
+ fields = JSONField(_('fields'), default=[], blank=True, null=True, help_text='字段信息')
|
|
| 61 |
+ |
|
| 62 |
+ class Meta: |
|
| 63 |
+ verbose_name = _('隔离点用户录入信息')
|
|
| 64 |
+ verbose_name_plural = _('隔离点用户录入信息')
|
|
| 65 |
+ |
|
| 66 |
+ unique_together = ( |
|
| 67 |
+ ('point_id', 'user_id'),
|
|
| 68 |
+ ) |
|
| 69 |
+ |
|
| 70 |
+ def __unicode__(self): |
|
| 71 |
+ return self.pk |
|
| 72 |
+ |
|
| 73 |
+ @property |
|
| 74 |
+ def data(self): |
|
| 75 |
+ return {
|
|
| 76 |
+ 'point_id': self.point_id, |
|
| 77 |
+ 'user_id': self.user_id, |
|
| 78 |
+ 'fields': self.fields, |
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ |
|
| 45 | 82 |
class ThermometerEquipmentInfo(BaseModelMixin): |
| 46 | 83 |
ONLINE = 1 |
| 47 | 84 |
OFFLINE = 0 |
@@ -70,6 +107,8 @@ class ThermometerEquipmentInfo(BaseModelMixin): |
||
| 70 | 107 |
active_at = models.DateTimeField(_('active_at'), blank=True, null=True, help_text=_('激活时间'))
|
| 71 | 108 |
|
| 72 | 109 |
# 用户基本信息 |
| 110 |
+ ipui_pk = models.IntegerField(_('ipui_pk'), default=0, help_text='隔离点用户录入PK')
|
|
| 111 |
+ |
|
| 73 | 112 |
name = models.CharField(_('name'), max_length=255, blank=True, null=True, help_text='用户姓名')
|
| 74 | 113 |
sex = models.IntegerField(_('sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text='用户性别')
|
| 75 | 114 |
birth_stamp = models.BigIntegerField(_('birth_stamp'), default=0, help_text='生日时间戳')
|
@@ -1,2 +1,4 @@ |
||
| 1 |
+pywe-miniapp==1.1.6 |
|
| 1 | 2 |
pywe-oauth==1.1.1 |
| 2 | 3 |
pywe-pay==1.0.14 |
| 4 |
+pywe-storage==1.0.1 |